1
2
3
4
5
6
7 package io.vavr.collection;
8
9
10
11
12
13 import java.io.Serializable;
14
15 import java.util.Collection;
16
17
18
19
20
21
22 interface ArrayType<T> {
23 @SuppressWarnings("unchecked")
24 static <T> ArrayType<T> obj() { return (ArrayType<T>) ObjectArrayType.INSTANCE; }
25
26 Class<T> type();
27 int lengthOf(Object array);
28 T getAt(Object array, int index);
29
30 Object empty();
31 void setAt(Object array, int index, T value) throws ClassCastException;
32 Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size);
33
34 @SuppressWarnings("unchecked")
35 static <T> ArrayType<T> of(Object array) { return of((Class<T>) array.getClass().getComponentType()); }
36 static <T> ArrayType<T> of(Class<T> type) { return !type.isPrimitive() ? obj() : ofPrimitive(type); }
37 @SuppressWarnings("unchecked")
38 static <T> ArrayType<T> ofPrimitive(Class<T> type) {
39 if (boolean.class == type) {
40 return (ArrayType<T>) BooleanArrayType.INSTANCE;
41 } else if (byte.class == type) {
42 return (ArrayType<T>) ByteArrayType.INSTANCE;
43 } else if (char.class == type) {
44 return (ArrayType<T>) CharArrayType.INSTANCE;
45 } else if (double.class == type) {
46 return (ArrayType<T>) DoubleArrayType.INSTANCE;
47 } else if (float.class == type) {
48 return (ArrayType<T>) FloatArrayType.INSTANCE;
49 } else if (int.class == type) {
50 return (ArrayType<T>) IntArrayType.INSTANCE;
51 } else if (long.class == type) {
52 return (ArrayType<T>) LongArrayType.INSTANCE;
53 } else if (short.class == type) {
54 return (ArrayType<T>) ShortArrayType.INSTANCE;
55 } else {
56 throw new IllegalArgumentException(String.valueOf(type));
57 }
58 }
59
60 default Object newInstance(int length) { return copy(empty(), length); }
61
62
63 default Object copyRange(Object array, int from, int to) {
64 final int length = to - from;
65 return copy(array, length, from, 0, length);
66 }
67
68
69 default Object grouped(Object array, int groupSize) {
70 final int arrayLength = lengthOf(array);
71 final Object results = obj().newInstance(1 + ((arrayLength - 1) / groupSize));
72 obj().setAt(results, 0, copyRange(array, 0, groupSize));
73
74 for (int start = groupSize, i = 1; start < arrayLength; i++) {
75 final int nextLength = Math.min(groupSize, arrayLength - (i * groupSize));
76 obj().setAt(results, i, copyRange(array, start, start + nextLength));
77 start += nextLength;
78 }
79
80 return results;
81 }
82
83
84 default Object copyUpdate(Object array, int index, T element) {
85 final Object copy = copy(array, index + 1);
86 setAt(copy, index, element);
87 return copy;
88 }
89
90 default Object copy(Object array, int minLength) {
91 final int arrayLength = lengthOf(array);
92 final int length = Math.max(arrayLength, minLength);
93 return copy(array, length, 0, 0, arrayLength);
94 }
95
96
97 default Object copyDrop(Object array, int index) {
98 final int length = lengthOf(array);
99 return copy(array, length, index, index, length - index);
100 }
101
102
103 default Object copyTake(Object array, int lastIndex) {
104 return copyRange(array, 0, lastIndex + 1);
105 }
106
107
108 default Object asArray(T element) {
109 final Object result = newInstance(1);
110 setAt(result, 0, element);
111 return result;
112 }
113
114
115 static Object[] asArray(java.util.Iterator<?> it, int length) {
116 final Object[] array = new Object[length];
117 for (int i = 0; i < length; i++) {
118 array[i] = it.next();
119 }
120 return array;
121 }
122
123 @SuppressWarnings("unchecked")
124 static <T> T asPrimitives(Class<?> primitiveClass, Iterable<?> values) {
125 final Object[] array = Array.ofAll(values).toJavaArray();
126 final ArrayType<T> type = of((Class<T>) primitiveClass);
127 final Object results = type.newInstance(array.length);
128 for (int i = 0; i < array.length; i++) {
129 type.setAt(results, i, (T) array[i]);
130 }
131 return (T) results;
132 }
133
134 final class BooleanArrayType implements ArrayType<Boolean>, Serializable {
135 private static final long serialVersionUID = 1L;
136 static final BooleanArrayType INSTANCE = new BooleanArrayType();
137 static final boolean[] EMPTY = new boolean[0];
138
139 private static boolean[] cast(Object array) { return (boolean[]) array; }
140
141 @Override
142 public Class<Boolean> type() { return boolean.class; }
143
144 @Override
145 public boolean[] empty() { return EMPTY; }
146
147 @Override
148 public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; }
149
150 @Override
151 public Boolean getAt(Object array, int index) { return cast(array)[index]; }
152
153 @Override
154 public void setAt(Object array, int index, Boolean value) throws ClassCastException {
155 if (value != null) {
156 cast(array)[index] = value;
157 } else {
158 throw new ClassCastException();
159 }
160 }
161
162 @Override
163 public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
164 return (size > 0)
165 ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size)
166 : new boolean[arraySize];
167 }
168 private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
169 final boolean[] result = new boolean[arraySize];
170 System.arraycopy(array, sourceFrom, result, destinationFrom, size);
171 return result;
172 }
173 }
174
175 final class ByteArrayType implements ArrayType<Byte>, Serializable {
176 private static final long serialVersionUID = 1L;
177 static final ByteArrayType INSTANCE = new ByteArrayType();
178 static final byte[] EMPTY = new byte[0];
179
180 private static byte[] cast(Object array) { return (byte[]) array; }
181
182 @Override
183 public Class<Byte> type() { return byte.class; }
184
185 @Override
186 public byte[] empty() { return EMPTY; }
187
188 @Override
189 public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; }
190
191 @Override
192 public Byte getAt(Object array, int index) { return cast(array)[index]; }
193
194 @Override
195 public void setAt(Object array, int index, Byte value) throws ClassCastException {
196 if (value != null) {
197 cast(array)[index] = value;
198 } else {
199 throw new ClassCastException();
200 }
201 }
202
203 @Override
204 public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
205 return (size > 0)
206 ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size)
207 : new byte[arraySize];
208 }
209 private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
210 final byte[] result = new byte[arraySize];
211 System.arraycopy(array, sourceFrom, result, destinationFrom, size);
212 return result;
213 }
214 }
215
216 final class CharArrayType implements ArrayType<Character>, Serializable {
217 private static final long serialVersionUID = 1L;
218 static final CharArrayType INSTANCE = new CharArrayType();
219 static final char[] EMPTY = new char[0];
220
221 private static char[] cast(Object array) { return (char[]) array; }
222
223 @Override
224 public Class<Character> type() { return char.class; }
225
226 @Override
227 public char[] empty() { return EMPTY; }
228
229 @Override
230 public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; }
231
232 @Override
233 public Character getAt(Object array, int index) { return cast(array)[index]; }
234
235 @Override
236 public void setAt(Object array, int index, Character value) throws ClassCastException {
237 if (value != null) {
238 cast(array)[index] = value;
239 } else {
240 throw new ClassCastException();
241 }
242 }
243
244 @Override
245 public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
246 return (size > 0)
247 ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size)
248 : new char[arraySize];
249 }
250 private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
251 final char[] result = new char[arraySize];
252 System.arraycopy(array, sourceFrom, result, destinationFrom, size);
253 return result;
254 }
255 }
256
257 final class DoubleArrayType implements ArrayType<Double>, Serializable {
258 private static final long serialVersionUID = 1L;
259 static final DoubleArrayType INSTANCE = new DoubleArrayType();
260 static final double[] EMPTY = new double[0];
261
262 private static double[] cast(Object array) { return (double[]) array; }
263
264 @Override
265 public Class<Double> type() { return double.class; }
266
267 @Override
268 public double[] empty() { return EMPTY; }
269
270 @Override
271 public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; }
272
273 @Override
274 public Double getAt(Object array, int index) { return cast(array)[index]; }
275
276 @Override
277 public void setAt(Object array, int index, Double value) throws ClassCastException {
278 if (value != null) {
279 cast(array)[index] = value;
280 } else {
281 throw new ClassCastException();
282 }
283 }
284
285 @Override
286 public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
287 return (size > 0)
288 ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size)
289 : new double[arraySize];
290 }
291 private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
292 final double[] result = new double[arraySize];
293 System.arraycopy(array, sourceFrom, result, destinationFrom, size);
294 return result;
295 }
296 }
297
298 final class FloatArrayType implements ArrayType<Float>, Serializable {
299 private static final long serialVersionUID = 1L;
300 static final FloatArrayType INSTANCE = new FloatArrayType();
301 static final float[] EMPTY = new float[0];
302
303 private static float[] cast(Object array) { return (float[]) array; }
304
305 @Override
306 public Class<Float> type() { return float.class; }
307
308 @Override
309 public float[] empty() { return EMPTY; }
310
311 @Override
312 public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; }
313
314 @Override
315 public Float getAt(Object array, int index) { return cast(array)[index]; }
316
317 @Override
318 public void setAt(Object array, int index, Float value) throws ClassCastException {
319 if (value != null) {
320 cast(array)[index] = value;
321 } else {
322 throw new ClassCastException();
323 }
324 }
325
326 @Override
327 public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
328 return (size > 0)
329 ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size)
330 : new float[arraySize];
331 }
332 private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
333 final float[] result = new float[arraySize];
334 System.arraycopy(array, sourceFrom, result, destinationFrom, size);
335 return result;
336 }
337 }
338
339 final class IntArrayType implements ArrayType<Integer>, Serializable {
340 private static final long serialVersionUID = 1L;
341 static final IntArrayType INSTANCE = new IntArrayType();
342 static final int[] EMPTY = new int[0];
343
344 private static int[] cast(Object array) { return (int[]) array; }
345
346 @Override
347 public Class<Integer> type() { return int.class; }
348
349 @Override
350 public int[] empty() { return EMPTY; }
351
352 @Override
353 public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; }
354
355 @Override
356 public Integer getAt(Object array, int index) { return cast(array)[index]; }
357
358 @Override
359 public void setAt(Object array, int index, Integer value) throws ClassCastException {
360 if (value != null) {
361 cast(array)[index] = value;
362 } else {
363 throw new ClassCastException();
364 }
365 }
366
367 @Override
368 public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
369 return (size > 0)
370 ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size)
371 : new int[arraySize];
372 }
373 private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
374 final int[] result = new int[arraySize];
375 System.arraycopy(array, sourceFrom, result, destinationFrom, size);
376 return result;
377 }
378 }
379
380 final class LongArrayType implements ArrayType<Long>, Serializable {
381 private static final long serialVersionUID = 1L;
382 static final LongArrayType INSTANCE = new LongArrayType();
383 static final long[] EMPTY = new long[0];
384
385 private static long[] cast(Object array) { return (long[]) array; }
386
387 @Override
388 public Class<Long> type() { return long.class; }
389
390 @Override
391 public long[] empty() { return EMPTY; }
392
393 @Override
394 public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; }
395
396 @Override
397 public Long getAt(Object array, int index) { return cast(array)[index]; }
398
399 @Override
400 public void setAt(Object array, int index, Long value) throws ClassCastException {
401 if (value != null) {
402 cast(array)[index] = value;
403 } else {
404 throw new ClassCastException();
405 }
406 }
407
408 @Override
409 public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
410 return (size > 0)
411 ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size)
412 : new long[arraySize];
413 }
414 private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
415 final long[] result = new long[arraySize];
416 System.arraycopy(array, sourceFrom, result, destinationFrom, size);
417 return result;
418 }
419 }
420
421 final class ShortArrayType implements ArrayType<Short>, Serializable {
422 private static final long serialVersionUID = 1L;
423 static final ShortArrayType INSTANCE = new ShortArrayType();
424 static final short[] EMPTY = new short[0];
425
426 private static short[] cast(Object array) { return (short[]) array; }
427
428 @Override
429 public Class<Short> type() { return short.class; }
430
431 @Override
432 public short[] empty() { return EMPTY; }
433
434 @Override
435 public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; }
436
437 @Override
438 public Short getAt(Object array, int index) { return cast(array)[index]; }
439
440 @Override
441 public void setAt(Object array, int index, Short value) throws ClassCastException {
442 if (value != null) {
443 cast(array)[index] = value;
444 } else {
445 throw new ClassCastException();
446 }
447 }
448
449 @Override
450 public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
451 return (size > 0)
452 ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size)
453 : new short[arraySize];
454 }
455 private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
456 final short[] result = new short[arraySize];
457 System.arraycopy(array, sourceFrom, result, destinationFrom, size);
458 return result;
459 }
460 }
461
462 final class ObjectArrayType implements ArrayType<Object>, Serializable {
463 private static final long serialVersionUID = 1L;
464 static final ObjectArrayType INSTANCE = new ObjectArrayType();
465 static final Object[] EMPTY = new Object[0];
466
467 private static Object[] cast(Object array) { return (Object[]) array; }
468
469 @Override
470 public Class<Object> type() { return Object.class; }
471
472 @Override
473 public Object[] empty() { return EMPTY; }
474
475 @Override
476 public int lengthOf(Object array) { return (array != null) ? cast(array).length : 0; }
477
478 @Override
479 public Object getAt(Object array, int index) { return cast(array)[index]; }
480
481 @Override
482 public void setAt(Object array, int index, Object value) {
483 cast(array)[index] = value;
484 }
485
486 @Override
487 public Object copy(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
488 return (size > 0)
489 ? copyNonEmpty(array, arraySize, sourceFrom, destinationFrom, size)
490 : new Object[arraySize];
491 }
492 private static Object copyNonEmpty(Object array, int arraySize, int sourceFrom, int destinationFrom, int size) {
493 final Object[] result = new Object[arraySize];
494 System.arraycopy(array, sourceFrom, result, destinationFrom, size);
495 return result;
496 }
497 }
498 }